{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial 5: Uplift modeling"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"../../imgs/lightautoml_logo_color.png\" alt=\"LightAutoML logo\" style=\"width:100%;\"/>"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Official LightAutoML github repository is [here](https://github.com/sb-ai-lab/LightAutoML)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Install LightAutoML"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Uncomment if doesn't clone repository by git. (ex.: colab, kaggle version)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#! pip install -U lightautoml"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Import necessary libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Standard python libraries\n",
    "from copy import deepcopy\n",
    "import os\n",
    "import requests\n",
    "\n",
    "# Installed libraries\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.metrics import roc_auc_score\n",
    "from sklearn.model_selection import train_test_split\n",
    "import torch\n",
    "\n",
    "# Imports from our package\n",
    "from lightautoml.automl.presets.tabular_presets import TabularAutoML\n",
    "from lightautoml.dataset.roles import DatetimeRole\n",
    "from lightautoml.tasks import Task\n",
    "\n",
    "from lightautoml.addons.uplift.base import AutoUplift, BaseLearnerWrapper, MetaLearnerWrapper\n",
    "from lightautoml.addons.uplift import metalearners\n",
    "from lightautoml.addons.uplift.metrics import (_available_uplift_modes,\n",
    "                                               TUpliftMetric,\n",
    "                                               calculate_graphic_uplift_curve,\n",
    "                                               calculate_min_max_uplift_auc,\n",
    "                                               calculate_uplift_at_top,\n",
    "                                               calculate_uplift_auc,\n",
    "                                               perfect_uplift_curve)\n",
    "from lightautoml.addons.uplift.utils import create_linear_automl\n",
    "from lightautoml.report.report_deco import ReportDecoUplift\n",
    "\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N_THREADS = 8 # threads cnt for lgbm and linear models\n",
    "N_FOLDS = 5 # folds cnt for AutoML\n",
    "RANDOM_STATE = 42 # fixed random state for various reasons\n",
    "TEST_SIZE = 0.2 # Test size for metric check\n",
    "TIMEOUT = 300 # Time in seconds for automl run\n",
    "TARGET_NAME = 'TARGET' # Target column name\n",
    "TREATMENT_NAME = 'CODE_GENDER'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fix torch number of threads and numpy seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(RANDOM_STATE)\n",
    "torch.set_num_threads(N_THREADS)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example data load"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load a dataset from the repository if doesn't clone repository by git."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "DATASET_DIR = '../data/'\n",
    "DATASET_NAME = 'sampled_app_train.csv'\n",
    "DATASET_FULLNAME = os.path.join(DATASET_DIR, DATASET_NAME)\n",
    "DATASET_URL = 'https://raw.githubusercontent.com/sb-ai-lab/LightAutoML/master/examples/data/sampled_app_train.csv'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "if not os.path.exists(DATASET_FULLNAME):\n",
    "    os.makedirs(DATASET_DIR, exist_ok=True)\n",
    "\n",
    "    dataset = requests.get(DATASET_URL).text\n",
    "    with open(DATASET_FULLNAME, 'w') as output:\n",
    "        output.write(dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "data = pd.read_csv(DATASET_FULLNAME)\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (Optional) Some user feature preparation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time \n",
    "\n",
    "data['BIRTH_DATE'] = (np.datetime64('2018-01-01') + data['DAYS_BIRTH'].astype(np.dtype('timedelta64[D]'))).astype(str)\n",
    "data['EMP_DATE'] = (np.datetime64('2018-01-01') + np.clip(data['DAYS_EMPLOYED'], None, 0).astype(np.dtype('timedelta64[D]'))\n",
    "                    ).astype(str)\n",
    "data['report_dt'] = np.datetime64('2018-01-01')\n",
    "data['constant'] = 1\n",
    "data['allnan'] = np.nan\n",
    "data.drop(['DAYS_BIRTH', 'DAYS_EMPLOYED'], axis=1, inplace=True)\n",
    "data['CODE_GENDER'] = (data['CODE_GENDER'] == 'M').astype(int)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data splitting for train-test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "\n",
    "stratify_value = data[TARGET_NAME] + 10 * data[TREATMENT_NAME]\n",
    "train, test = train_test_split(data, test_size=3000, stratify=stratify_value, random_state=42)\n",
    "test_target, test_treatment = test[TARGET_NAME].values.ravel(), test[TREATMENT_NAME].values.ravel()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup columns roles"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "roles = {\n",
    "    'target': TARGET_NAME,\n",
    "    'treatment': TREATMENT_NAME,\n",
    "    DatetimeRole(base_date=True, seasonality=(), base_feats=False): 'report_dt'\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AutoUplift (use predefined uplift methods)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fit autouplift"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "task = Task('binary')\n",
    "\n",
    "autouplift = AutoUplift(task,\n",
    "                        metric='adj_qini', \n",
    "                        has_report=True,\n",
    "                        test_size=0.2, \n",
    "                        timeout=200,\n",
    "                        # timeout_metalearner=5\n",
    ")\n",
    "\n",
    "autouplift.fit(train, roles, verbose=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Show rating of uplift methods (meta-learners)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "rating_table = autouplift.get_metalearners_rating()\n",
    "rating_table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Get best metalearner"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time \n",
    "\n",
    "best_metalearner = autouplift.create_best_metalearner(\n",
    "    update_metalearner_params={'timeout': None},\n",
    "    update_baselearner_params={'timeout': 30}\n",
    ")\n",
    "best_metalearner.fit(train, roles)\n",
    "_ = best_metalearner.predict(test);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Predict to test data and check metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "uplift_pred, treatment_pred, control_pred = best_metalearner.predict(test)\n",
    "uplift_pred = uplift_pred.ravel()\n",
    "\n",
    "roc_auc_treatment = roc_auc_score(test_target[test_treatment == 1], treatment_pred[test_treatment == 1])\n",
    "roc_auc_control = roc_auc_score(test_target[test_treatment == 0], control_pred[test_treatment == 0])\n",
    "\n",
    "uplift_auc_algo = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=False)\n",
    "uplift_auc_algo_normed = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=True)\n",
    "auc_base, auc_perfect = calculate_min_max_uplift_auc(test_target, test_treatment)\n",
    "\n",
    "print('--- Check scores ---')\n",
    "print('OOF scores \"ROC_AUC\":')\n",
    "print('\\tTreatment = {:.5f}'.format(roc_auc_treatment))\n",
    "print('\\tControl   = {:.5f}'.format(roc_auc_control))\n",
    "print('Uplift score of test group (default=\"adj_qini\"):')\n",
    "print('\\tBaseline      = {:.5f}'.format(auc_base))\n",
    "print('\\tAlgo (Normed) = {:.5f} ({:.5f})'.format(uplift_auc_algo, uplift_auc_algo_normed))\n",
    "print('\\tPerfect       = {:.5f}'.format(auc_perfect))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AutoUplift (custom uplift methods)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fit autouplift"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "# Set uplift candidate for choosing best of them\n",
    "# !!!ATTENTION!!!\n",
    "#    This is a demonstration of the possibilities, \n",
    "#    You may use default set of candidates \n",
    "\n",
    "task = Task('binary')\n",
    "\n",
    "uplift_candidates = [\n",
    "    MetaLearnerWrapper(\n",
    "        name='TLearner__Default', \n",
    "        klass=metalearners.TLearner, \n",
    "        params={'base_task': task}\n",
    "    ),  \n",
    "    MetaLearnerWrapper(\n",
    "        name='TLearner__Custom', \n",
    "        klass=metalearners.TLearner, \n",
    "        params={\n",
    "            'treatment_learner': BaseLearnerWrapper(\n",
    "                name='__TabularAutoML__',\n",
    "                klass=TabularAutoML, \n",
    "                params={'task': task, 'timeout': 10}),\n",
    "            'control_learner': BaseLearnerWrapper(\n",
    "                name='__Linear__',\n",
    "                klass=create_linear_automl,\n",
    "                params={'task': Task('binary')})\n",
    "        }\n",
    "    ),\n",
    "    MetaLearnerWrapper(\n",
    "        name='XLearner__Custom',\n",
    "        klass=metalearners.XLearner,\n",
    "        params={\n",
    "            'outcome_learners': [\n",
    "                TabularAutoML(task=task, timeout=10), # [sec] , Only speed up example, don't change it!\n",
    "                create_linear_automl(task=Task('binary'))\n",
    "            ],\n",
    "            'effect_learners': [BaseLearnerWrapper(\n",
    "                name='__TabularAutoML__',\n",
    "                klass=TabularAutoML, \n",
    "                params={'task': Task('reg'), 'timeout': 5})],\n",
    "            'propensity_learner': create_linear_automl(task=Task('binary')),\n",
    "        }    \n",
    "    )\n",
    "]\n",
    "\n",
    "autouplift = AutoUplift(task,\n",
    "                        uplift_candidates=uplift_candidates, \n",
    "                        metric='adj_qini', \n",
    "                        test_size=0.2, \n",
    "                        threshold_imbalance_treatment=0.0,    # Doesn't affect, see warnings\n",
    "                        timeout=600)                          # Doesn't affect, see warnings\n",
    "\n",
    "autouplift.fit(train, roles, verbose=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Show rating of uplift methods (meta-learners)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "rating_table = autouplift.get_metalearners_rating()\n",
    "rating_table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Predict to test data and check metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "uplift_pred, treatment_pred, control_pred = autouplift.predict(test)\n",
    "uplift_pred = uplift_pred.ravel()\n",
    "\n",
    "roc_auc_treatment = roc_auc_score(test_target[test_treatment == 1], treatment_pred[test_treatment == 1])\n",
    "roc_auc_control = roc_auc_score(test_target[test_treatment == 0], control_pred[test_treatment == 0])\n",
    "\n",
    "uplift_auc_algo = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=False)\n",
    "uplift_auc_algo_normed = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=True)\n",
    "auc_base, auc_perfect = calculate_min_max_uplift_auc(test_target, test_treatment)\n",
    "\n",
    "print('--- Check scores ---')\n",
    "print('OOF scores \"ROC_AUC\":')\n",
    "print('\\tTreatment = {:.5f}'.format(roc_auc_treatment))\n",
    "print('\\tControl   = {:.5f}'.format(roc_auc_control))\n",
    "print('Uplift score of test group (default=\"adj_qini\"):')\n",
    "print('\\tBaseline      = {:.5f}'.format(auc_base))\n",
    "print('\\tAlgo (Normed) = {:.5f} ({:.5f})'.format(uplift_auc_algo, uplift_auc_algo_normed))\n",
    "print('\\tPerfect       = {:.5f}'.format(auc_perfect))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AutoUplift with custom metric"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fit autouplift"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "# Using a custom metric\n",
    "# How to determine custom metric, see below\n",
    "\n",
    "task = Task('binary')\n",
    "\n",
    "\n",
    "class CustomUpliftMetric(TUpliftMetric):\n",
    "    def __call__(self, target: np.ndarray, uplift_pred: np.ndarray, treatment: np.ndarray) -> float:\n",
    "        up_10 = calculate_uplift_at_top(target, uplift_pred, treatment, 10)\n",
    "        up_20 = calculate_uplift_at_top(target, uplift_pred, treatment, 20)\n",
    "    \n",
    "        return 0.5 * (up_10 + up_20)\n",
    "\n",
    "autouplift = AutoUplift(task,\n",
    "                        add_dd_candidates=True,\n",
    "                        metric=CustomUpliftMetric(), \n",
    "                        test_size=0.2, \n",
    "                        threshold_imbalance_treatment=0.0,\n",
    "                        cpu_limit=10,\n",
    "                        timeout=100)\n",
    "\n",
    "autouplift.fit(train, roles)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Show rating of uplift methods (meta-learners)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "rating_table = autouplift.get_metalearners_rating()\n",
    "rating_table"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## MetaLearner"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TLearner"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Fit on train data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "# Default setting\n",
    "tlearner = metalearners.TLearner(base_task=Task('binary'), cpu_limit=5)\n",
    "tlearner.fit(train, roles)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Predict to test data and check metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "uplift_pred, treatment_pred, control_pred = tlearner.predict(test)\n",
    "uplift_pred = uplift_pred.ravel()\n",
    "\n",
    "roc_auc_treatment = roc_auc_score(test_target[test_treatment == 1], treatment_pred[test_treatment == 1])\n",
    "roc_auc_control = roc_auc_score(test_target[test_treatment == 0], control_pred[test_treatment == 0])\n",
    "\n",
    "uplift_auc_algo = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=False)\n",
    "uplift_auc_algo_normed = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=True)\n",
    "auc_base, auc_perfect = calculate_min_max_uplift_auc(test_target, test_treatment)\n",
    "\n",
    "print('--- Check scores ---')\n",
    "print('OOF scores \"ROC_AUC\":')\n",
    "print('\\tTreatment = {:.5f}'.format(roc_auc_treatment))\n",
    "print('\\tControl   = {:.5f}'.format(roc_auc_control))\n",
    "print('Uplift score of test group (default=\"adj_qini\"):')\n",
    "print('\\tBaseline      = {:.5f}'.format(auc_base))\n",
    "print('\\tAlgo (Normed) = {:.5f} ({:.5f})'.format(uplift_auc_algo, uplift_auc_algo_normed))\n",
    "print('\\tPerfect       = {:.5f}'.format(auc_perfect))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### XLearner"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Fit on train data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "# Custom base algorithm\n",
    "xlearner = metalearners.XLearner(\n",
    "    propensity_learner=TabularAutoML(task=Task('binary'), timeout=10),\n",
    "    outcome_learners=[\n",
    "        TabularAutoML(task=Task('binary'), timeout=10),\n",
    "        TabularAutoML(task=Task('binary'), timeout=10)\n",
    "    ],\n",
    "    effect_learners=[\n",
    "        TabularAutoML(task=Task('reg'), timeout=10),\n",
    "        TabularAutoML(task=Task('reg'), timeout=10)\n",
    "    ]\n",
    ")\n",
    "xlearner.fit(train, roles)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Predict to test data and check metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "uplift_pred, treatment_pred, control_pred = xlearner.predict(test)\n",
    "uplift_pred = uplift_pred.ravel()\n",
    "\n",
    "roc_auc_treatment = roc_auc_score(test_target[test_treatment == 1], treatment_pred[test_treatment == 1])\n",
    "roc_auc_control = roc_auc_score(test_target[test_treatment == 0], control_pred[test_treatment == 0])\n",
    "\n",
    "uplift_auc_algo = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=False)\n",
    "uplift_auc_algo_normed = calculate_uplift_auc(test_target, uplift_pred, test_treatment, normed=True)\n",
    "auc_base, auc_perfect = calculate_min_max_uplift_auc(test_target, test_treatment)\n",
    "\n",
    "print('--- Check scores ---')\n",
    "print('OOF scores \"ROC_AUC\":')\n",
    "print('\\tTreatment = {:.5f}'.format(roc_auc_treatment))\n",
    "print('\\tControl   = {:.5f}'.format(roc_auc_control))\n",
    "print('Uplift score of test group (default=\"adj_qini\"):')\n",
    "print('\\tBaseline      = {:.5f}'.format(auc_base))\n",
    "print('\\tAlgo (Normed) = {:.5f} ({:.5f})'.format(uplift_auc_algo, uplift_auc_algo_normed))\n",
    "print('\\tPerfect       = {:.5f}'.format(auc_perfect))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Uplift metrics and graphics (using xlearner predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time \n",
    "\n",
    "UPLIFT_METRIC = 'adj_qini'\n",
    "\n",
    "print(\"All available uplift metrics: {}\".format(_available_uplift_modes))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Algorithm uplift curve "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "# Algorithm curve\n",
    "xs_xlearner, ys_xlearner = calculate_graphic_uplift_curve(\n",
    "    test_target, uplift_pred, test_treatment, mode=UPLIFT_METRIC\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Baseline, perfect curve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Baseline curve\n",
    "xs_base, ys_base = xs_xlearner, xs_xlearner * ys_xlearner[-1]\n",
    "\n",
    "# Perfect curver\n",
    "perfect_uplift = perfect_uplift_curve(test_target, test_treatment)\n",
    "xs_perfect, ys_perfect = calculate_graphic_uplift_curve(\n",
    "    test_target, perfect_uplift, test_treatment, mode=UPLIFT_METRIC)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(10, 7))\n",
    "\n",
    "plt.plot(xs_base, ys_base, 'black')\n",
    "plt.plot(xs_xlearner, ys_xlearner, 'red')\n",
    "plt.plot(xs_perfect, ys_perfect, 'green')\n",
    "\n",
    "plt.fill_between(xs_xlearner, ys_base, ys_xlearner, alpha=0.5, color='orange')\n",
    "\n",
    "plt.xlabel('Cumulative percentage of people in T/C groups')\n",
    "plt.ylabel('Uplift metric (%s)'.format(UPLIFT_METRIC))\n",
    "plt.grid()\n",
    "plt.legend(['Baseline', 'XLearner', 'Perfect']);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Uplift TOP-K"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tops = np.arange(5, 101, 5)\n",
    "\n",
    "uplift_at_tops = []\n",
    "for top in tops:\n",
    "    uat = calculate_uplift_at_top(test_target, uplift_pred, test_treatment, top=top)\n",
    "    uplift_at_tops.append(uat)\n",
    "\n",
    "plt.figure(figsize=(10, 7))\n",
    "\n",
    "plt.plot(tops, uplift_at_tops, marker='.')\n",
    "\n",
    "plt.legend(['Uplift_At_K'])\n",
    "plt.xticks(np.arange(0, 101, 10))\n",
    "plt.grid()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Custom metric"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Custom metric can be used in AutoUplift\n",
    "# There msut be a function's signature:\n",
    "# def custom_metric(target, uplift_pred, treatment) -> float:\n",
    "\n",
    "\n",
    "class CustomUpliftMetric(TUpliftMetric):\n",
    "    def __call__(self, target: np.ndarray, uplift_pred: np.ndarray, treatment: np.ndarray) -> float:\n",
    "        up_10 = calculate_uplift_at_top(target, uplift_pred, treatment, 10)\n",
    "        up_20 = calculate_uplift_at_top(target, uplift_pred, treatment, 20)\n",
    "    \n",
    "        return 0.5 * (up_10 + up_20)\n",
    "\n",
    "\n",
    "metric = CustomUpliftMetric()\n",
    "metric_value = metric(test_target, uplift_pred, test_treatment)\n",
    "\n",
    "print(\"Metric = {}\".format(metric_value))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Report"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "\n",
    "RDU = ReportDecoUplift()\n",
    "tlearner_deco = RDU(metalearners.TLearner(base_task=Task('binary')))\n",
    "tlearner_deco.fit(train, roles)\n",
    "_ = tlearner_deco.predict(test)\n",
    "\n",
    "# Path to report: PATH_TO_CURRENT_NOTEBOOK/lama_report/lama_interactive_report.html"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "bf9424b8e3052bddf6726e3cb8e5d28a2d26679b29382f5380215b73dc612d6f"
  },
  "kernelspec": {
   "display_name": "0.4.0.dev2",
   "language": "python",
   "name": "0.4.0.dev2"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "349.091px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
